﻿using BattleFury.Layers;
using BattleFury.Lib.Graphics;
using BattleFury.Lib.Maps.Data;
using BattleFury.Lib.Tiles;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace BattleFury.Lib.Maps
{
	public class CollisionLayer
		: BaseLayer, ILayer
	{
		private readonly CollisionTile[,] _tiles;
		private readonly Texture2D _whitePixel;

		public string Name { get; set; }
		public Vector2 Size { get; private set; }
		public Vector2 TileSize { get; set; }
        //public bool IsEnabled { get; set; }
        //public bool IsVisible { get; set; }
		public Color Tint { get; set; }
		public Camera Camera { get; set; }

		public Rectangle this[int x, int y]
		{
			get
			{
				if (_tiles.GetUpperBound(0) < x || _tiles.GetUpperBound(1) < y || x < 0 || y < 0) return Rectangle.Empty;
				var tile = _tiles[x, y];
				return tile == null 
						? Rectangle.Empty 
						: new Rectangle((int)(x * TileSize.X), (int)(y * TileSize.Y), (int)TileSize.X, (int)TileSize.Y);
			}
		}

		public CollisionLayer(Vector2 size, Vector2 tileSize)
		{
			Size = size;
			TileSize = tileSize;
			IsEnabled = true;
			IsVisible = false;

			_tiles = new CollisionTile[(int)size.X, (int)size.Y];

			_whitePixel = RenderEngine.Get().Textures["WhitePixel"];

			Tint = Color.Red.WithOpacity(0.5f);
		}

		public Vector2 GetLocation(Vector2 absoluteLocation)
		{
			return new Vector2(absoluteLocation.X / TileSize.X, absoluteLocation.Y / TileSize.Y);
		}

        //public void Update(GameTime gameTime)
        //{
        //    if (!IsEnabled) return;
        //}

		public void Draw(GameTime gameTime, SpriteBatch spriteBatch)
		{
			if (!IsVisible) return;

			var minX = (int)(Camera.Position.X / TileSize.X);
			var minY = (int)(Camera.Position.Y / TileSize.Y);
			var maxX = (int)((Camera.Position.X + Camera.Size.X) / TileSize.X) + 1;
			var maxY = (int)((Camera.Position.Y + Camera.Size.Y) / TileSize.Y) + 1;

			if (minX < 0) minX = 0;
			if (minY < 0) minY = 0;
			if (maxX > _tiles.GetUpperBound(0) + 1) maxX = _tiles.GetUpperBound(0) + 1;
			if (maxY > _tiles.GetUpperBound(1) + 1) maxY = _tiles.GetUpperBound(1) + 1;

			for (var y = minY; y < maxY; y++)
			{
				for (var x = minX; x < maxX; x++)
				{
					var tile = _tiles[x, y];
					if (tile == null) continue;
					var rect = new Rectangle((int) (x * TileSize.X), (int) (y * TileSize.Y), (int) TileSize.X, (int) TileSize.Y);
					spriteBatch.Draw(_whitePixel, rect, Tint);
				}
			}
		}

		public void SetTile(int x, int y, CollisionTile tile)
		{
			_tiles[x, y] = tile;
		}

		public static CollisionLayer LoadFrom(Vector2 size, CollisionLayerData data)
		{
			var tileSize = new Vector2(data.TileWidth, data.TileHeight);
			var ret = new CollisionLayer(size, tileSize);

			foreach (var tileData in data.Tiles)
			{
				var tile = new CollisionTile();
				ret.SetTile(tileData.X, tileData.Y, tile);
			}

			return ret;
		}
	
		public bool CheckCollisions(Rectangle bounds)
		{
			// TODO: Add region exclusions instead of entire set
			for (var y = 0; y < Size.Y; y++)
			{
				for (var x = 0; x < Size.X; x++)
				{
					var tile = _tiles[x, y];
					if (tile != null)
					{
						var tileBounds = new Rectangle((int) (x*TileSize.X), (int) (y*TileSize.Y), (int) TileSize.X, (int) TileSize.Y);
						if (tileBounds.Intersects(bounds)) return true;
					}
				}
			}
			return false;
		}
	}
}